package com.inspur.edp.ai.flow.spi;

import com.fasterxml.jackson.databind.JsonNode;
import com.inspur.edp.ai.flow.exception.FlowException;
import com.inspur.edp.ai.flow.metadata.AbsNode;
import com.inspur.edp.common.type.enhanced.EnhancedServiceLoader;
import com.inspur.edp.common.type.utils.JsonPropUtil;
import com.inspur.edp.common.type.utils.JsonSerializeUtil;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.commons.utils.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lizhaorui
 * @date 2025/8/19
 * @description
 */
public class NodeDeserializerFactory {

    private static Map<String, NodeDeserializer> PROVIDER_MAP;

    public static NodeDeserializer get(String kind) {
        if (StringUtils.isEmpty(kind)) {
            throw new FlowException("node executor type can not be empty.");
        }
        if (PROVIDER_MAP == null) {
            synchronized (NodeCompileFactory.class) {
                if (PROVIDER_MAP == null) {
                    ConcurrentHashMap<String, NodeDeserializer> temp = new ConcurrentHashMap<>();
                    List<Object> objectList = EnhancedServiceLoader.loadFile("META-INF/services/" + NodeDeserializer.class.getName(), NodeDeserializerFactory.class.getClassLoader());
                    for (Object obj : objectList) {
                        NodeDeserializer nodeDeserializer = (NodeDeserializer) obj;
                        temp.put(nodeDeserializer.getKind(), nodeDeserializer);
                    }
                    PROVIDER_MAP = temp;
                }
            }
        }
        return PROVIDER_MAP.get(kind);
    }

    public static AbsNode deserialize(JsonNode jsonObject) {
        if (jsonObject == null) {
            return null;
        }
        String expressKind = JsonPropUtil.getPropValueAsString(jsonObject, "kind");
        if (StringUtils.isEmpty(expressKind)) {
            return null;
        }
        NodeDeserializer nodeDeserializer = NodeDeserializerFactory.get(expressKind);
        if (nodeDeserializer == null) {
            throw new FlowException(String.format("There is no %s expression deserializer", expressKind));
        }
        if (!jsonObject.isObject()) {
            throw new FlowException("json node must be object node.");
        }
        return (AbsNode) JsonSerializeUtil.toObject(jsonObject, nodeDeserializer.getNodeClass());
    }

}